﻿--[[
   @brief    layout manager
   @author   sogoodchen
   @version  1.0
   @date     2015-03-09
--]]

AutoCloseOpt = {
    kAutoClose = 1,  -- 自动关闭
    kHideInsteadRemove = 2, -- 只隐藏,不移除
};

layout_mgr =
{
    -- brief:  加载UI布局到根节点
    -- param: layout_path_u8  布局路径
    --        keep_state      hide_instead_remove 隐藏替代移除, 需要保持状态时填true
    -- return:                子布局根控件ID
    restore_layout = function(layout_path_u8, auto_close_opt)
        local ctrl_id = layout_mgr.restore_sub_layout(Tenio.ROOT_CONTROLID, layout_path_u8);
        layout_mgr.restored_layouts[ctrl_id] = { path = layout_path_u8,
                                                 auto_close_opt = auto_close_opt
                                               };
        return ctrl_id;
    end;

    -- brief:  加载UI布局到根节点
    -- param: layout_path_u8  布局路径
    --        keep_state      hide_instead_remove 隐藏替代移除, 需要保持状态时填true
    -- return:                子布局根控件ID
    restore_layout_ex = function(parent_id, layout_path_u8, auto_close_opt)
        local ctrl_id = layout_mgr.restore_sub_layout(parent_id, layout_path_u8);
        layout_mgr.restored_layouts[ctrl_id] = { path = layout_path_u8,
                                                 auto_close_opt = auto_close_opt
                                               };
        return ctrl_id;
    end;
    
        -- brief:  加载UI布局到根节点
    -- param: layout_path_u8  布局路径
    -- return:                子布局根控件ID
    -- note:   子布局根控件将被重命名，适用于子布局需要多次加载的情形
    restore_layout_multi = function(layout_path_u8)
        local ctrl_id =  layout_mgr.restore_sub_layout_multi(Tenio.ROOT_CONTROLID, layout_path_u8)
        layout_mgr.restored_layouts[ctrl_id] = { path = layout_path_u8
                                               };
        return ctrl_id;
    end;

    
    -- brief: 加载UI子布局到指定节点控件
    -- param: parent_id       节点控件ID
    -- param: layout_path_u8  子布局路径
    -- return:                子布局根控件ID
    restore_sub_layout = function(parent_id, layout_path_u8)
        local main_uilib = ui_utility.uilib();
        local const_ui_str, str_holder = U8toCUIStr(layout_path_u8);
        local sub_root_control_id = main_uilib:RestoreFromXMLNode(parent_id, const_ui_str, FALSE);
        base_utility.log("[layout_mgr] restore_sub_layout(parent="..tostring(parent_id)..
            ", layout="..layout_path_u8.."), sub_root=" .. tostring(sub_root_control_id));
        local param = {id = sub_root_control_id};
        event_center.send_event(layout_event.RESTORE_LAYOUT_FINISH, base_utility.table_to_json(param));
        local interface_type = ui_utility.get_type_name_by_id(sub_root_control_id);
        if interface_type == "Tenio::ITDialog" then
            layout_mgr.existing_dlg_ids[sub_root_control_id] = 1;
        end
        return sub_root_control_id;
    end;
    
    -- brief: 加载UI子布局到指定节点控件
    -- param: parent_id       节点控件ID
    -- param: layout_path_u8  子布局路径
    -- return:                子布局根控件ID
    -- note:   子布局根控件将被重命名，适用于子布局需要多次加载的情形
    restore_sub_layout_multi = function(parent_id, layout_path_u8)
        local main_uilib = ui_utility.uilib();
        local const_ui_str, str_holder = U8toCUIStr(layout_path_u8);
        local sub_root_control_id = main_uilib:RestoreFromXMLNodeUseIndexName(
                parent_id, const_ui_str, layout_mgr.layout_index, FALSE);
        base_utility.log("[layout_mgr] restore_sub_layout_multi(parent="..parent_id
                ..", layout="..layout_path_u8.."), sub_root=" .. sub_root_control_id);
        layout_mgr.layout_index = layout_mgr.layout_index + 1;
        local interface_type = ui_utility.get_type_name_by_id(sub_root_control_id);
        if interface_type == "Tenio::ITDialog" then
            layout_mgr.existing_dlg_ids[sub_root_control_id] = 1;
        end
        return sub_root_control_id;
    end;
    
    -- brief: 加载N个UI子布局到指定节点控件
    -- param: parent_id       节点控件ID
    -- param: layout_path_u8  子布局路径
    -- param: count           加载子布局的个数
    -- return:                子布局根控件ID列表: {[0]=id_1, [1]=id_2, ...}
    -- note:   子布局根控件将被重命名，适用于子布局需要多次加载的情形
    restore_sub_layouts = function(parent_id, layout_path_u8, count)
        local cur_cnt = 0;
        local sub_root_id_tbl = {}
        while cur_cnt < count do
            local sub_root_id = layout_mgr.restore_sub_layout_multi(parent_id, layout_path_u8);
            sub_root_id_tbl[cur_cnt] = sub_root_id;
            cur_cnt = cur_cnt + 1;
        end
        return sub_root_id_tbl;
    end;
    
    -- brief: 延迟删除控件
    -- param: control_id       控件ID
    -- return:                
    -- note:   删除时机：下一个tick
    delay_remove_ctrl = function(control_id)
        base_utility.log("[layout_mgr]delay_remove_ctrl " .. tostring(control_id)); 
        
        local param = {id = control_id};
        event_center.send_event(layout_event.REMOVING_LAYOUT, base_utility.table_to_json(param));

        local tpfui =
            base_utility.get_component_adapter("ITpf_ui",
                "ierd_tgp.tpf_ui.GetTPFUI();");
        tpfui:DelayDeleteCtrl(control_id);
        layout_mgr.existing_dlg_ids[control_id] = nil;
        table.remove(layout_mgr.restored_layouts, control_id);
    end;

    -- brief: 立即删除控件
    -- param: control_id       控件ID
    -- return:                
    -- note:   谨慎使用，需确保调用堆栈不经过被删除的控件
    remove_ctrl = function(control_id) 
        local param = {id = control_id};
        event_center.send_event(layout_event.REMOVING_LAYOUT, base_utility.table_to_json(param));

        local main_uilib = ui_utility.uilib();
        main_uilib:DeleteControl(control_id);
        layout_mgr.existing_dlg_ids[control_id] = nil;
        table.remove(layout_mgr.restored_layouts, control_id);   
    end;
    
    -- brief: 加载根布局
    restore_root_layout = function()
        local main_uilib = ui_utility.uilib();
        local const_ui_str, str_holder = U8toCUIStr(layout_mgr.root_layout);
        local ret = main_uilib:RestoreFromXMLFile(const_ui_str, FALSE);
        local ret_str = (ret == TRUE) and "success" or "failed";
        base_utility.log("[layout_mgr] restore_root_layout("..layout_mgr.root_layout.."), ret=" .. ret_str);

        if (TRUE == ret) then
            local   pRoot = main_uilib:GetRootControlPtr();

            if nil ~= pRoot then
                ui_utility.setproperty_by_id(pRoot:GetControlID(), 
                        "OnClickNotify", "layout_mgr.OnClkNotify");
                comm_center.listen_broadcast("Brdcst_Exit_TGP", "layout_mgr.BeforeExit");
            else
                base_utility.log("[layout_mgr] Get root control pointer fail.");
            end;
        end;
    end;

    -- 根节点，点击上报
    OnClkNotify = function(nCtrlID, sPath)
        if nil == layout_mgr.cClickMap then
            layout_mgr.cClickMap = {};
        end;

        sPath = string.gsub(sPath, "\\", "/")

        local   nItem = layout_mgr.cClickMap[sPath];

        if nil == nItem then
            layout_mgr.cClickMap[sPath] = 1;
        else
            layout_mgr.cClickMap[sPath] = nItem + 1;
        end;

        base_utility.log("[layout_mgr] Click notify.");
    end;

    -- 点击数据上报
    BeforeExit = function(zMsg)
        if nil ~= next(layout_mgr.cClickMap) then
            local   zData = ierd_tgp.tpf_ui.LuaQosDataEx:new();

            zData.qos_kind = ierd_tgp.adapt_for_imports.qos.Qos_kind.kCommBtnClkRpt;
            zData.str_action = "ClkReport";
            zData.str_type = "ClkCount";

            local   sJson = nil;

            for sKey, nCnt in pairs(layout_mgr.cClickMap) do
                local   sItem = "'" .. sKey .. "':" .. tostring(nCnt);

                if (nil == sJson) or (#sJson + #sItem) < 620 then
                    if nil == sJson then
                        sJson = sItem;
                    else
                        sJson = sJson .. "," .. sItem;
                    end;
                else
                    zData.str_json = "{" .. sJson .. "}";
                    base_utility.lua_qos_ex(zData);

                    sJson = sItem;
                end;
            end;

            if nil ~= sJson and #sJson > 0 then
                zData.str_json = "{" .. sJson .. "}";
                base_utility.lua_qos_ex(zData);
            end;

            zData:delete();

            -- layout_mgr.cClickMap
            base_utility.log("[layout_mgr] Before exit, report click.");
        end;
    end;

    -- brief: 返回现存dlg的control ids
    get_existing_dlg_ids = function()
        return layout_mgr.existing_dlg_ids;
    end;

    auto_close_all = function()
        base_utility.log("[layout_mgr][auto_close_all]enter");
        for control_id, layout_desc in pairs(layout_mgr.restored_layouts) do
            if layout_desc.auto_close_opt == AutoCloseOpt.kAutoClose then
                layout_mgr.delay_remove_ctrl(control_id);
                base_utility.log("[layout_mgr][auto_close_all]remove " .. tostring(control_id) .. ":" ..
                                                               tostring(layout_desc.path));
            elseif layout_desc.auto_close_opt == AutoCloseOpt.kHideInsteadRemove then
                local result = ui_utility.show_ctrl(control_id, false);
                base_utility.log("[layout_mgr][auto_close_all]hide " .. tostring(result) .. ", " ..
                                    tostring(control_id) .. ":" .. tostring(layout_desc.path));
            else
                base_utility.log("[layout_mgr][auto_close_all]deep it " .. 
                                        tostring(control_id) .. ":" .. tostring(layout_desc.path));
            end
        end
    end;

    show_all_hiden = function()
        base_utility.log("[layout_mgr][show_all_hiden]enter");
        for control_id, layout_desc in pairs(layout_mgr.restored_layouts) do
            if layout_desc.auto_close_opt == AutoCloseOpt.kHideInsteadRemove then
                local result = ui_utility.show_ctrl(control_id, false);
                base_utility.log("[layout_mgr][show_all_hiden]show " .. tostring(result) .. ", " ..
                                    tostring(control_id) .. ":" .. tostring(layout_desc.path));
            else
                base_utility.log("[layout_mgr][show_all_hiden]do nothing for auto_close_opt:" ..
                                                         tostring(layout_desc.auto_close_opt) ..
                                                          ", " ..tostring(control_id) .. ":" ..
                                                         tostring(layout_desc.path));
            end
        end
    end;
    
    hide_all_window = function()
        for control_id, layout_desc in pairs(layout_mgr.restored_layouts) do
            ui_utility.show_ctrl(control_id, false);
        end
    end;

    root_layout = 'root.tpf';
    layout_index = 0;
    existing_dlg_ids = {};
    restored_layouts = {};

    -- 按钮点击数据上报
    cClickMap = {};           -- ButtonPath <==> {ID,Count}

};